home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume8 / unzipbsd < prev    next >
Encoding:
Text File  |  1989-09-30  |  58.8 KB  |  2,067 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Tektronix Inc., Beaverton, Or.
  3. subject: v08i089: unzipbsd 2.0
  4. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Reply-To: michaele@vice.ico.tek.com (Michael Enkelis)
  6.  
  7. Posting-number: Volume 8, Issue 89
  8. Submitted-by: michaele@vice.ico.tek.com (Michael Enkelis)
  9. Archive-name: unzipbsd
  10.  
  11. This should handle ZIP files made with version 1.1
  12.  
  13.  
  14. #! /bin/sh
  15. # This is a shell archive, meaning:
  16. # 1. Remove everything above the #! /bin/sh line.
  17. # 2. Save the resulting text in a file.
  18. # 3. Execute the file with /bin/sh (not csh) to create the files:
  19. #    Makefile
  20. #    unzipbsd.c
  21. #    crc32.c
  22. #    patchlevel.h
  23. #    unzip.doc
  24. # This archive created: Tue Sep 26 16:26:16 1989
  25. export PATH; PATH=/bin:$PATH
  26. echo shar: extracting "'Makefile'" '(928 characters)'
  27. if test -f 'Makefile'
  28. then
  29.     echo shar: will not over-write existing file "'Makefile'"
  30. else
  31. sed 's/^    X//' << \SHAR_EOF > 'Makefile'
  32.     X# Makefile for unzipbsd
  33.     X
  34.     X
  35.     X# "make unzip"    -- makes unzip in current directory
  36.     X# "make install"  -- makes unzip, then moves it into DESTDIR defined below
  37.     X# "make clean"    -- deletes object files and executable unzip from current dir
  38.     X# "make shar"     -- make a SHell ARchive
  39.     X# "make arc"      -- make a DOS archive
  40.     X
  41.     X# Directory where we want to move executable unzip on "make install"
  42.     XDESTDIR=/usr/public
  43.     X
  44.     X# CFLAGS are flags for the C compiler.  LDFLAGS are flags for the loader.
  45.     XCFLAGS= -O
  46.     X# This is used for DBX
  47.     X#CFLAGS= -g
  48.     X
  49.     XLDFLAGS= -s
  50.     X
  51.     XCC=cc
  52.     X
  53.     X.c.o:
  54.     X    $(CC) -c $(CFLAGS) $*.c
  55.     X
  56.     XSRCS = unzipbsd.c crc32.c patchlevel.h
  57.     XOBJS = unzipbsd.o crc32.o
  58.     X
  59.     Xunzip: $(OBJS)
  60.     X    cc $(LDFLAGS) -o unzip $(OBJS)
  61.     X
  62.     Xunzip.o: unzip.c
  63.     X
  64.     Xcrc32.o: crc32.c
  65.     X
  66.     Xinstall: unzip
  67.     X    mv unzip $(DESTDIR)/unzip
  68.     X
  69.     Xclean:
  70.     X    /bin/rm -f $(OBJS) core unzip
  71.     X
  72.     Xshar:
  73.     X    @shar -a Makefile $(SRCS) unzip.doc > unzipbsd.shar
  74.     X
  75.     Xarc:
  76.     X    @arc -a unzipbsd.arc Makefile $(SRCS) unzip.doc
  77.     X
  78. SHAR_EOF
  79. if test 928 -ne "`wc -c < 'Makefile'`"
  80. then
  81.     echo shar: error transmitting "'Makefile'" '(should have been 928 characters)'
  82. fi
  83. fi # end of overwriting check
  84. echo shar: extracting "'unzipbsd.c'" '(42309 characters)'
  85. if test -f 'unzipbsd.c'
  86. then
  87.     echo shar: will not over-write existing file "'unzipbsd.c'"
  88. else
  89. sed 's/^    X//' << \SHAR_EOF > 'unzipbsd.c'
  90.     X
  91.     X/*
  92.     X * Copyright 1989 Samuel H. Smith;  All rights reserved
  93.     X *
  94.     X * Do not distribute modified versions without my permission.
  95.     X * Do not remove or alter this notice or any other copyright notice.
  96.     X * If you use this in your own program you must distribute source code.
  97.     X * Do not use any of this in a commercial product.
  98.     X *
  99.     X */
  100.     X
  101.     X/*
  102.     X * UnZip - A simple zipfile extract utility
  103.     X *
  104.     X * To compile:
  105.     X *      tcc -B -O -Z -G -mc unzip.c        ;turbo C 2.0, compact model
  106.     X *
  107.     X */
  108.     X
  109.     X#include "patchlevel.h"
  110.     X#define VERSION  "2.0"
  111.     X
  112.     Xtypedef unsigned char byte;    /* code assumes UNSIGNED bytes */
  113.     Xtypedef long longint;
  114.     Xtypedef unsigned word;
  115.     Xtypedef char boolean;
  116.     X
  117.     X#define STRSIZ 256
  118.     X
  119.     X#include <stdio.h>
  120.     X /* this is your standard header for all C compiles */
  121.     X#include <ctype.h>
  122.     X
  123.     X#ifdef MSDOS || M_XENIX
  124.     X#include <stdlib.h>
  125.     X /* this include defines various standard library prototypes */
  126.     X#endif
  127.     X
  128.     X
  129.     X/*
  130.     X * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
  131.     X *
  132.     X */
  133.     X
  134.     X
  135.     X/* ----------------------------------------------------------- */
  136.     X/*
  137.     X * Zipfile layout declarations
  138.     X *
  139.     X */
  140.     X
  141.     X
  142.     Xchar local_file_header_signature[] = {0x50,0x4b,0x03,0x04};
  143.     X
  144.     X
  145.     Xtypedef struct local_file_header {
  146.     X    word version_needed_to_extract;
  147.     X    word general_purpose_bit_flag;
  148.     X    word compression_method;
  149.     X    word last_mod_file_time;
  150.     X    word last_mod_file_date;
  151.     X    longint crc32;
  152.     X    longint compressed_size;
  153.     X    longint uncompressed_size;
  154.     X    word filename_length;
  155.     X    word extra_field_length;
  156.     X} local_file_header;
  157.     X
  158.     X
  159.     Xchar central_file_header_signature[] = {0x50,0x4b,0x01,0x02};
  160.     X
  161.     X
  162.     Xtypedef struct central_directory_file_header {
  163.     X    word version_made_by;
  164.     X    word version_needed_to_extract;
  165.     X    word general_purpose_bit_flag;
  166.     X    word compression_method;
  167.     X    word last_mod_file_time;
  168.     X    word last_mod_file_date;
  169.     X    longint crc32;
  170.     X    longint compressed_size;
  171.     X    longint uncompressed_size;
  172.     X    word filename_length;
  173.     X    word extra_field_length;
  174.     X    word file_comment_length;
  175.     X    word disk_number_start;
  176.     X    word internal_file_attributes;
  177.     X    longint external_file_attributes;
  178.     X    longint relative_offset_local_header;
  179.     X} central_directory_file_header;
  180.     X
  181.     X
  182.     Xchar end_central_dir_signature[] = {0x50,0x4b,0x05,0x06};
  183.     X
  184.     X
  185.     Xtypedef struct end_central_dir_record {
  186.     X    word number_this_disk;
  187.     X    word number_disk_with_start_central_directory;
  188.     X    word total_entries_central_dir_on_this_disk;
  189.     X    word total_entries_central_dir;
  190.     X    longint size_central_directory;
  191.     X    longint offset_start_central_directory;
  192.     X    word zipfile_comment_length;
  193.     X} end_central_dir_record;
  194.     X
  195.     X
  196.     X
  197.     X/* ----------------------------------------------------------- */
  198.     X/*
  199.     X * input file variables
  200.     X *
  201.     X */
  202.     X
  203.     X#define INBUFSIZ 0x2000
  204.     Xbyte *inbuf;            /* input file buffer - any size is legal */
  205.     Xbyte *inptr;
  206.     Xbyte *comment;
  207.     X
  208.     Xint incnt;
  209.     Xunsigned bitbuf;
  210.     Xint bits_left;
  211.     Xboolean zipeof;
  212.     X
  213.     Xint zipfd;
  214.     Xchar zipfn[STRSIZ];
  215.     Xlocal_file_header lrec;
  216.     X
  217.     X
  218.     X/* ----------------------------------------------------------- */
  219.     X/*
  220.     X * output stream variables
  221.     X *
  222.     X */
  223.     X
  224.     X#define OUTBUFSIZ 0x6000
  225.     Xbyte *outbuf;                   /* buffer for rle look-back */
  226.     Xbyte *outptr;
  227.     X
  228.     Xlongint outpos;            /* absolute position in outfile */
  229.     Xint outcnt;            /* current position in outbuf */
  230.     X
  231.     Xint outfd;
  232.     Xchar filename[STRSIZ];
  233.     Xchar extra[STRSIZ];
  234.     X
  235.     X#define DLE 144
  236.     X
  237.     X
  238.     X/* ----------------------------------------------------------- */
  239.     X/*
  240.     X * shrink/reduce working storage
  241.     X *
  242.     X */
  243.     X
  244.     Xint factor;
  245.     Xbyte followers[256][64];
  246.     Xbyte Slen[256];
  247.     X
  248.     X#define max_bits 13
  249.     X#define init_bits 9
  250.     X#define hsize 8192
  251.     X#define first_ent 257
  252.     X#define clear 256
  253.     X
  254.     Xtypedef int hsize_array_integer[hsize+1];
  255.     Xtypedef byte hsize_array_byte[hsize+1];
  256.     X
  257.     Xhsize_array_integer prefix_of;
  258.     Xhsize_array_byte suffix_of;
  259.     Xhsize_array_byte stack;
  260.     X
  261.     Xint codesize;
  262.     Xint maxcode;
  263.     Xint free_ent;
  264.     Xint maxcodemax;
  265.     Xint offset;
  266.     Xint sizex;
  267.     X
  268.     X
  269.     X
  270.     X/* ============================================================= */
  271.     X/*
  272.     X * Host operating system details
  273.     X *
  274.     X */
  275.     X
  276.     X#include <string.h>
  277.     X /* this include defines strcpy, strcmp, etc. */
  278.     X
  279.     X#include <time.h>
  280.     X
  281.     X#ifdef MSDOS || M_XENIX
  282.     X#include <io.h>
  283.     X /*
  284.     X  * this include file defines
  285.     X  *             struct ftime ...        (* file time/date stamp info *)
  286.     X  *             int setftime (int handle, struct ftime *ftimep);
  287.     X  *             #define SEEK_CUR  1     (* lseek() modes *)
  288.     X  *             #define SEEK_END  2
  289.     X  *             #define SEEK_SET  0
  290.     X  */
  291.     X#else
  292.     X#include <sys/file.h>
  293.     X /*
  294.     X  * this include file defines
  295.     X  *             #define L_SET 0  (* Seek to absolute record *)
  296.     X  */
  297.     X#define SEEK_SET L_SET
  298.     X#endif
  299.     X
  300.     X
  301.     X
  302.     X#ifdef MSDOS || M_XENIX
  303.     X#include <fcntl.h>
  304.     X /*
  305.     X  * this include file defines
  306.     X  *             #define O_BINARY 0x8000  (* no cr-lf translation *)
  307.     X  * as used in the open() standard function
  308.     X  */
  309.     X#ifndef L_SET
  310.     X#define L_SET 1
  311.     X#endif
  312.     X#endif
  313.     X
  314.     X#ifndef O_BINARY
  315.     X#define O_BINARY 0        /* BSD don't have a Open_BINARY mode */
  316.     X#endif
  317.     X
  318.     X#include <sys/types.h>
  319.     X#include <sys/stat.h>
  320.     X /*
  321.     X  * this include file defines
  322.     X  *             #define S_IREAD 0x0100  (* owner may read *)
  323.     X  *             #define S_IWRITE 0x0080 (* owner may write *)
  324.     X  * as used in the creat() standard function
  325.     X  */
  326.     X
  327.     Xvoid set_file_time()
  328.     X /*
  329.     X  * set the output file date/time stamp according to information from the
  330.     X  * zipfile directory record for this file 
  331.     X  */
  332.     X{
  333.     X    /*
  334.     X     * set output file date and time - this is optional and can be
  335.     X     * deleted
  336.     X     */
  337.     X
  338.     X#define leap(y)     (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  339.     X#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
  340.     X
  341.     X    byte    yr, mo, dy;    /* parts of a date */
  342.     X    byte    hh, mm, ss;    /* parts of a time */
  343.     X    static char month_lengths[] =
  344.     X        { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  345.     X    int day_of_year, year;
  346.     X    struct utimbuf {
  347.     X        time_t actime;        /* file accessed time */
  348.     X        time_t modtime;        /* file updated time */
  349.     X    } times;
  350.     X
  351.     X    yr = (lrec.last_mod_file_date >> 9) & 0x7f;    /* dissect the date */
  352.     X    mo = (lrec.last_mod_file_date >> 5) & 0x0f;
  353.     X    dy = lrec.last_mod_file_date & 0x1f;
  354.     X
  355.     X    hh = (lrec.last_mod_file_time >> 11) & 0x1f;    /* dissect the time */
  356.     X    mm = (lrec.last_mod_file_time >> 5) & 0x3f;
  357.     X    ss = (lrec.last_mod_file_time & 0x1f) * 2;
  358.     X    yr = (yr + 80) % 100;
  359.     X    year = yr + 1900;
  360.     X
  361.     X    /*
  362.     X     * this is the standard Unix implementation (also fully
  363.     X     * compatible with MSC)
  364.     X     */
  365.     X
  366.     X    close(outfd);
  367.     X    if (mo < 1 || mo > 12 || dy < 1 || dy > month_lengths[mo-1]
  368.     X        && !(mo == 2 && dy == 29 && leap (year))
  369.     X        || hh > 23 || mm > 59 || ss > 59)
  370.     X        return;
  371.     X
  372.     X    day_of_year = dy - 1;
  373.     X    if (mo > 2 && leap(year))
  374.     X        ++day_of_year;
  375.     X
  376.     X    while (--mo > 0)
  377.     X        day_of_year += month_lengths[mo - 1];
  378.     X
  379.     X    times.modtime = (86400 * (long)(day_of_year + 365 * (year - 1970) 
  380.     X        + nleap (year)) + 3600 * (hh-1) + 60 * mm + ss);
  381.     X
  382.     X#ifdef    HAVE_TZ
  383.     X    tzset();
  384.     X    times.modtime += timezone;
  385.     X#endif    /* HAVE_TZ */
  386.     X    times.actime = times.modtime;
  387.     X    utime(filename, ×);
  388.     X}
  389.     X
  390.     X/*
  391.     X * Some defines to use the GETOPT functions
  392.     X * that are on most systems, even TURBO-C has these.
  393.     X */
  394.     X#define USE_GETOPT        /* Use the GETOPT package */
  395.     Xint extract   = 1;        /* Extract contents */
  396.     Xint debugging = 0;        /* debug enable */
  397.     Xint verbose   = 0;        /* be verbose */
  398.     Xint list_zip  = 0;        /* list contents only */
  399.     Xint test_zip  = 0;        /* test CRC's only */
  400.     Xint unixfy    = 1;        /* Convert filename to lowercase */
  401.     Xint dsp_comment  = 1;        /* Display comments */
  402.     X
  403.     Xlong crc32val;            /* The CRC value we calculate */
  404.     Xint numbad =0;
  405.     Xint Total_files =0;
  406.     Xlong Total_bytes =0;
  407.     Xlong Total_length =0;
  408.     X
  409.     X/* ============================================================= */
  410.     X
  411.     Xint create_output_file()
  412.     X /* return non-0 if creat failed */
  413.     X{
  414.     X    if (!extract)
  415.     X        return 0;
  416.     X
  417.     X    /* create the output file with READ and WRITE permissions */
  418.     X    outfd = creat(filename, S_IWRITE | S_IREAD);
  419.     X    if (outfd < 1) {
  420.     X        printf("Can't create output: %s\n", filename);
  421.     X        return 1;
  422.     X    }
  423.     X
  424.     X    /*
  425.     X     * close the newly created file and reopen it in BINARY mode to
  426.     X     * disable all CR/LF translations 
  427.     X     */
  428.     X    close(outfd);
  429.     X    outfd = open(filename, O_RDWR | O_BINARY);
  430.     X
  431.     X    /* write a single byte at EOF to pre-allocate the file */
  432.     X        lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET);
  433.     X    write(outfd, "?", 1);
  434.     X    lseek(outfd, 0L, SEEK_SET);
  435.     X    return 0;
  436.     X}
  437.     X
  438.     X
  439.     Xint open_input_file()
  440.     X /* return non-0 if creat failed */
  441.     X{
  442.     X    /*
  443.     X     * open the zipfile for reading and in BINARY mode to prevent cr/lf
  444.     X     * translation, which would corrupt the bitstreams 
  445.     X     */
  446.     X
  447.     X    zipfd = open(zipfn, O_RDONLY | O_BINARY);
  448.     X    if (zipfd < 1) {
  449.     X        printf("Can't open input file: %s\n", zipfn);
  450.     X        return (1);
  451.     X    }
  452.     X    return 0;
  453.     X}
  454.     X
  455.     X
  456.     Xint FillBuffer()
  457.     X /* fill input buffer if possible */
  458.     X{
  459.     X    int readsize;
  460.     X
  461.     X        if (lrec.compressed_size <= 0)
  462.     X        return incnt = 0;
  463.     X
  464.     X        if (lrec.compressed_size > INBUFSIZ)
  465.     X        readsize = INBUFSIZ;
  466.     X    else
  467.     X                readsize = (int) lrec.compressed_size;
  468.     X    incnt = read(zipfd, inbuf, readsize);
  469.     X
  470.     X        lrec.compressed_size -= incnt;
  471.     X    inptr = inbuf;
  472.     X    return incnt--;
  473.     X}
  474.     X
  475.     Xint ReadByte(x)
  476.     Xunsigned *x;
  477.     X /* read a byte; return 8 if byte available, 0 if not */
  478.     X{
  479.     X    if (incnt-- == 0)
  480.     X        if (FillBuffer() == 0)
  481.     X            return 0;
  482.     X
  483.     X    *x = *inptr++;
  484.     X    return 8;
  485.     X}
  486.     X
  487.     X
  488.     X/* ------------------------------------------------------------- */
  489.     Xstatic unsigned mask_bits[] =
  490.     X        {0,     0x0001, 0x0003, 0x0007, 0x000f,
  491.     X                0x001f, 0x003f, 0x007f, 0x00ff,
  492.     X                0x01ff, 0x03ff, 0x07ff, 0x0fff,
  493.     X                0x1fff, 0x3fff, 0x7fff, 0xffff
  494.     X        };
  495.     X
  496.     X
  497.     Xint FillBitBuffer(bits)
  498.     Xregister int bits;
  499.     X{
  500.     X    /* get the bits that are left and read the next word */
  501.     X    unsigned temp;
  502.     X        register int result = bitbuf;
  503.     X    int sbits = bits_left;
  504.     X    bits -= bits_left;
  505.     X
  506.     X    /* read next word of input */
  507.     X    bits_left = ReadByte(&bitbuf);
  508.     X    bits_left += ReadByte(&temp);
  509.     X    bitbuf |= (temp << 8);
  510.     X    if (bits_left == 0)
  511.     X        zipeof = 1;
  512.     X
  513.     X    /* get the remaining bits */
  514.     X        result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  515.     X        bitbuf >>= bits;
  516.     X        bits_left -= bits;
  517.     X        return result;
  518.     X}
  519.     X
  520.     X#define READBIT(nbits,zdest,ztype) \
  521.     X    { if (nbits <= bits_left) \
  522.     X        { zdest = ztype(bitbuf & mask_bits[nbits]);\
  523.     X        bitbuf >>= nbits; bits_left -= nbits; }\
  524.     X    else zdest = ztype(FillBitBuffer(nbits));}
  525.     X
  526.     X/*
  527.     X * macro READBIT(nbits,zdest,ztype)
  528.     X *  {
  529.     X *      if (nbits <= bits_left) {
  530.     X *          zdest = ztype(bitbuf & mask_bits[nbits]);
  531.     X *          bitbuf >>= nbits;
  532.     X *          bits_left -= nbits;
  533.     X *      } else
  534.     X *          zdest = ztype(FillBitBuffer(nbits));
  535.     X *  }
  536.     X *
  537.     X */
  538.     X
  539.     X
  540.     X/* ------------------------------------------------------------- */
  541.     X
  542.     Xvoid Write_file()
  543.     X{
  544.     X    if (extract)
  545.     X        write(outfd, outbuf, outcnt);
  546.     X}
  547.     X
  548.     X/* ------------------------------------------------------------- */
  549.     X
  550.     Xvoid FlushOutput()
  551.     X /* flush contents of output buffer */
  552.     X{
  553.     X    UpdateCRC(outbuf, outcnt);
  554.     X    Write_file();
  555.     X    outpos += outcnt;
  556.     X    outcnt = 0;
  557.     X    outptr = outbuf;
  558.     X}
  559.     X
  560.     X#define OUTB(intc) { *outptr++=intc; if (++outcnt==OUTBUFSIZ) FlushOutput(); }
  561.     X
  562.     X/*
  563.     X *  macro OUTB(intc)
  564.     X *  {
  565.     X *      *outptr++=intc;
  566.     X *      if (++outcnt==OUTBUFSIZ)
  567.     X *          FlushOutput();
  568.     X *  }
  569.     X *
  570.     X */
  571.     X
  572.     X
  573.     X/* ----------------------------------------------------------- */
  574.     X
  575.     Xvoid LoadFollowers()
  576.     X{
  577.     X        register int x;
  578.     X        register int i;
  579.     X
  580.     X    for (x = 255; x >= 0; x--) {
  581.     X                READBIT(6,Slen[x],(byte));
  582.     X        for (i = 0; i < Slen[x]; i++) {
  583.     X                        READBIT(8,followers[x][i],(byte));
  584.     X        }
  585.     X    }
  586.     X}
  587.     X
  588.     X/* ----------------------------------------------------------- */
  589.     X/*
  590.     X * The Reducing algorithm is actually a combination of two
  591.     X * distinct algorithms.  The first algorithm compresses repeated
  592.     X * byte sequences, and the second algorithm takes the compressed
  593.     X * stream from the first algorithm and applies a probabilistic
  594.     X * compression method.
  595.     X */
  596.     X
  597.     Xint L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
  598.     X
  599.     Xint D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
  600.     Xint D_mask[]  = {0, 0x01, 0x03, 0x07, 0x0f};
  601.     X
  602.     Xint B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
  603.     X         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
  604.     X         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  605.     X         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
  606.     X         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  607.     X         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  608.     X         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  609.     X         7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  610.     X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  611.     X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  612.     X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  613.     X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  614.     X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  615.     X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  616.     X         8, 8, 8, 8};
  617.     X
  618.     X/* ----------------------------------------------------------- */
  619.     X
  620.     Xvoid unReduce()
  621.     X /* expand probablisticly reduced data */
  622.     X{
  623.     X        register int lchar;
  624.     X        int nchar;
  625.     X        int ExState;
  626.     X        int V;
  627.     X        int Len;
  628.     X
  629.     X        factor = lrec.compression_method - 1;
  630.     X    ExState = 0;
  631.     X    lchar = 0;
  632.     X    LoadFollowers();
  633.     X
  634.     X        while (((outpos + outcnt) < lrec.uncompressed_size) && (!zipeof)) {
  635.     X        if (Slen[lchar] == 0)
  636.     X                        READBIT(8,nchar,(int))      /* ; */
  637.     X                else
  638.     X        {
  639.     X                        READBIT(1,nchar,(int));
  640.     X                        if (nchar != 0)
  641.     X                                READBIT(8,nchar,(int))      /* ; */
  642.     X                        else
  643.     X            {
  644.     X                                int follower;
  645.     X                                int bitsneeded = B_table[Slen[lchar]];
  646.     X                                READBIT(bitsneeded,follower,(int));
  647.     X                                nchar = followers[lchar][follower];
  648.     X            }
  649.     X        }
  650.     X
  651.     X        /* expand the resulting byte */
  652.     X        switch (ExState) {
  653.     X
  654.     X        case 0:
  655.     X                        if (nchar != DLE)
  656.     X                                OUTB(nchar) /*;*/
  657.     X            else
  658.     X                ExState = 1;
  659.     X            break;
  660.     X
  661.     X        case 1:
  662.     X                        if (nchar != 0) {
  663.     X                                V = nchar;
  664.     X                Len = V & L_table[factor];
  665.     X                if (Len == L_table[factor])
  666.     X                    ExState = 2;
  667.     X                else
  668.     X                    ExState = 3;
  669.     X            }
  670.     X            else {
  671.     X                                OUTB(DLE);
  672.     X                ExState = 0;
  673.     X            }
  674.     X            break;
  675.     X
  676.     X                case 2: {
  677.     X                                Len += nchar;
  678.     X                ExState = 3;
  679.     X            }
  680.     X            break;
  681.     X
  682.     X                case 3: {
  683.     X                register int i = Len + 3;
  684.     X                int offset = (((V >> D_shift[factor]) &
  685.     X                                          D_mask[factor]) << 8) + nchar + 1;
  686.     X                longint op = outpos + outcnt - offset;
  687.     X
  688.     X                /* special case- before start of file */
  689.     X                while ((op < 0L) && (i > 0)) {
  690.     X                    OUTB(0);
  691.     X                    op++;
  692.     X                    i--;
  693.     X                }
  694.     X
  695.     X                /* normal copy of data from output buffer */
  696.     X                {
  697.     X                    register int ix = (int) (op % OUTBUFSIZ);
  698.     X
  699.     X                                        /* do a block memory copy if possible */
  700.     X                                        if ( ((ix    +i) < OUTBUFSIZ) &&
  701.     X                                             ((outcnt+i) < OUTBUFSIZ) ) {
  702.     X                                                memcpy(outptr,&outbuf[ix],i);
  703.     X                                                outptr += i;
  704.     X                                                outcnt += i;
  705.     X                                        }
  706.     X
  707.     X                                        /* otherwise copy byte by byte */
  708.     X                                        else while (i--) {
  709.     X                                                OUTB(outbuf[ix]);
  710.     X                                                if (++ix >= OUTBUFSIZ)
  711.     X                                                        ix = 0;
  712.     X                                        }
  713.     X                                }
  714.     X
  715.     X                ExState = 0;
  716.     X            }
  717.     X            break;
  718.     X        }
  719.     X
  720.     X                /* store character for next iteration */
  721.     X                lchar = nchar;
  722.     X        }
  723.     X}
  724.     X
  725.     X
  726.     X/* ------------------------------------------------------------- */
  727.     X/*
  728.     X * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
  729.     X * with partial clearing.
  730.     X *
  731.     X */
  732.     X
  733.     Xvoid partial_clear()
  734.     X{
  735.     X        register int pr;
  736.     X        register int cd;
  737.     X
  738.     X    /* mark all nodes as potentially unused */
  739.     X    for (cd = first_ent; cd < free_ent; cd++)
  740.     X        prefix_of[cd] |= 0x8000;
  741.     X
  742.     X    /* unmark those that are used by other nodes */
  743.     X    for (cd = first_ent; cd < free_ent; cd++) {
  744.     X        pr = prefix_of[cd] & 0x7fff;    /* reference to another node? */
  745.     X                if (pr >= first_ent)            /* flag node as referenced */
  746.     X            prefix_of[pr] &= 0x7fff;
  747.     X    }
  748.     X
  749.     X    /* clear the ones that are still marked */
  750.     X    for (cd = first_ent; cd < free_ent; cd++)
  751.     X        if ((prefix_of[cd] & 0x8000) != 0)
  752.     X            prefix_of[cd] = -1;
  753.     X
  754.     X    /* find first cleared node as next free_ent */
  755.     X        cd = first_ent;
  756.     X        while ((cd < maxcodemax) && (prefix_of[cd] != -1))
  757.     X                cd++;
  758.     X        free_ent = cd;
  759.     X}
  760.     X
  761.     X
  762.     X/* ------------------------------------------------------------- */
  763.     X
  764.     Xvoid unShrink()
  765.     X{
  766.     X#define  GetCode(dest) READBIT(codesize,dest,(int))
  767.     X
  768.     X    register int code;
  769.     X    register int stackp;
  770.     X    int finchar;
  771.     X    int oldcode;
  772.     X    int incode;
  773.     X
  774.     X
  775.     X    /* decompress the file */
  776.     X    maxcodemax = 1 << max_bits;
  777.     X    codesize = init_bits;
  778.     X    maxcode = (1 << codesize) - 1;
  779.     X    free_ent = first_ent;
  780.     X    offset = 0;
  781.     X    sizex = 0;
  782.     X
  783.     X    for (code = maxcodemax; code > 255; code--)
  784.     X        prefix_of[code] = -1;
  785.     X
  786.     X    for (code = 255; code >= 0; code--) {
  787.     X        prefix_of[code] = 0;
  788.     X        suffix_of[code] = code;
  789.     X    }
  790.     X
  791.     X    GetCode(oldcode);
  792.     X    if (zipeof)
  793.     X        return;
  794.     X    finchar = oldcode;
  795.     X
  796.     X        OUTB(finchar);
  797.     X
  798.     X        stackp = hsize;
  799.     X
  800.     X    while (!zipeof) {
  801.     X        GetCode(code);
  802.     X        if (zipeof)
  803.     X            return;
  804.     X
  805.     X        while (code == clear) {
  806.     X            GetCode(code);
  807.     X            switch (code) {
  808.     X
  809.     X            case 1:{
  810.     X                    codesize++;
  811.     X                    if (codesize == max_bits)
  812.     X                        maxcode = maxcodemax;
  813.     X                    else
  814.     X                        maxcode = (1 << codesize) - 1;
  815.     X                }
  816.     X                break;
  817.     X
  818.     X            case 2:
  819.     X                partial_clear();
  820.     X                break;
  821.     X            }
  822.     X
  823.     X            GetCode(code);
  824.     X            if (zipeof)
  825.     X                return;
  826.     X        }
  827.     X
  828.     X
  829.     X        /* special case for KwKwK string */
  830.     X        incode = code;
  831.     X        if (prefix_of[code] == -1) {
  832.     X                        stack[--stackp] = finchar;
  833.     X            code = oldcode;
  834.     X        }
  835.     X
  836.     X
  837.     X        /* generate output characters in reverse order */
  838.     X        while (code >= first_ent) {
  839.     X                        stack[--stackp] = suffix_of[code];
  840.     X            code = prefix_of[code];
  841.     X        }
  842.     X
  843.     X        finchar = suffix_of[code];
  844.     X                stack[--stackp] = finchar;
  845.     X
  846.     X
  847.     X                /* and put them out in forward order, block copy */
  848.     X                if ((hsize-stackp+outcnt) < OUTBUFSIZ) {
  849.     X                        memcpy(outptr,&stack[stackp],hsize-stackp);
  850.     X                        outptr += hsize-stackp;
  851.     X                        outcnt += hsize-stackp;
  852.     X                        stackp = hsize;
  853.     X                }
  854.     X
  855.     X                /* output byte by byte if we can't go by blocks */
  856.     X                else while (stackp < hsize)
  857.     X                        OUTB(stack[stackp++]);
  858.     X
  859.     X
  860.     X        /* generate new entry */
  861.     X        code = free_ent;
  862.     X        if (code < maxcodemax) {
  863.     X            prefix_of[code] = oldcode;
  864.     X            suffix_of[code] = finchar;
  865.     X
  866.     X            do
  867.     X                code++;
  868.     X            while ((code < maxcodemax) && (prefix_of[code] != -1));
  869.     X
  870.     X            free_ent = code;
  871.     X        }
  872.     X
  873.     X        /* remember previous code */
  874.     X        oldcode = incode;
  875.     X    }
  876.     X
  877.     X}
  878.     X
  879.     X/* ------------------------------------------------------------- */ 
  880.     X/*
  881.     X * Imploding
  882.     X * ---------
  883.     X *
  884.     X * The Imploding algorithm is actually a combination of two distinct
  885.     X * algorithms.  The first algorithm compresses repeated byte sequences
  886.     X * using a sliding dictionary.  The second algorithm is used to compress
  887.     X * the encoding of the sliding dictionary ouput, using multiple
  888.     X * Shannon-Fano trees.
  889.     X *
  890.     X */ 
  891.     X
  892.     X#define maxSF 256
  893.     X
  894.     X   typedef struct sf_entry { 
  895.     X                 word         Code; 
  896.     X                 byte         Value; 
  897.     X                 byte         BitLength; 
  898.     X              } sf_entry; 
  899.     X
  900.     X   typedef struct sf_tree {   /* a shannon-fano tree */ 
  901.     X      sf_entry     entry[maxSF];
  902.     X      int          entries;
  903.     X      int          MaxLength;
  904.     X   } sf_tree; 
  905.     X
  906.     X   typedef sf_tree      *sf_treep; 
  907.     X
  908.     X   sf_tree      lit_tree; 
  909.     X   sf_tree      length_tree; 
  910.     X   sf_tree      distance_tree; 
  911.     X   boolean      lit_tree_present; 
  912.     X   boolean      eightK_dictionary; 
  913.     X   int          minimum_match_length;
  914.     X   int          dict_bits;
  915.     X
  916.     X
  917.     Xvoid SortLengths(tree)
  918.     Xsf_tree *tree;
  919.     X  /* Sort the Bit Lengths in ascending order, while retaining the order
  920.     X    of the original lengths stored in the file */ 
  921.     X{ 
  922.     X   int          x;
  923.     X   int          gap;
  924.     X   sf_entry     t; 
  925.     X   boolean      noswaps;
  926.     X   int          a, b;
  927.     X
  928.     X   gap = tree->entries / 2; 
  929.     X
  930.     X   do { 
  931.     X      do { 
  932.     X         noswaps = 1;
  933.     X         for (x = 0; x <= (tree->entries - 1) - gap; x++) 
  934.     X         { 
  935.     X            a = tree->entry[x].BitLength; 
  936.     X            b = tree->entry[x + gap].BitLength; 
  937.     X            if ((a > b) || ((a == b) && (tree->entry[x].Value > tree->entry[x + gap].Value))) 
  938.     X            { 
  939.     X               t = tree->entry[x]; 
  940.     X               tree->entry[x] = tree->entry[x + gap]; 
  941.     X               tree->entry[x + gap] = t; 
  942.     X               noswaps = 0;
  943.     X            } 
  944.     X         } 
  945.     X      }  while (!noswaps);
  946.     X
  947.     X      gap = gap / 2; 
  948.     X   }  while (gap > 0);
  949.     X} 
  950.     X
  951.     X
  952.     X/* ----------------------------------------------------------- */ 
  953.     X
  954.     Xvoid ReadLengths(tree)
  955.     Xsf_tree *tree;
  956.     X{ 
  957.     X   int          treeBytes;
  958.     X   int          i;
  959.     X   int          num, len;
  960.     X
  961.     X  /* get number of bytes in compressed tree */
  962.     X   READBIT(8,treeBytes,(int));
  963.     X   treeBytes++; 
  964.     X   i = 0; 
  965.     X
  966.     X   tree->MaxLength = 0;
  967.     X
  968.     X /* High 4 bits: Number of values at this bit length + 1. (1 - 16)
  969.     X    Low  4 bits: Bit Length needed to represent value + 1. (1 - 16) */
  970.     X   while (treeBytes > 0)
  971.     X   {
  972.     X      READBIT(4,len,(int)); len++;
  973.     X      READBIT(4,num,(int)); num++;
  974.     X
  975.     X      while (num > 0)
  976.     X      {
  977.     X         if (len > tree->MaxLength)
  978.     X            tree->MaxLength = len;
  979.     X         tree->entry[i].BitLength = (byte) len;
  980.     X         tree->entry[i].Value = (byte) i;
  981.     X         i++;
  982.     X         num--;
  983.     X      }
  984.     X
  985.     X      treeBytes--;
  986.     X   } 
  987.     X} 
  988.     X
  989.     X
  990.     X/* ----------------------------------------------------------- */ 
  991.     X
  992.     Xvoid GenerateTrees(tree)
  993.     Xsf_tree *tree;
  994.     X     /* Generate the Shannon-Fano trees */ 
  995.     X{ 
  996.     X   word         Code;
  997.     X   int          CodeIncrement;
  998.     X   int          LastBitLength;
  999.     X   int          i;
  1000.     X
  1001.     X
  1002.     X   Code = 0;
  1003.     X   CodeIncrement = 0; 
  1004.     X   LastBitLength = 0; 
  1005.     X
  1006.     X   i = tree->entries - 1;   /* either 255 or 63 */ 
  1007.     X   while (i >= 0) 
  1008.     X   { 
  1009.     X      Code += CodeIncrement; 
  1010.     X      if (tree->entry[i].BitLength != (byte) LastBitLength) 
  1011.     X      { 
  1012.     X         LastBitLength = tree->entry[i].BitLength; 
  1013.     X         CodeIncrement = 1 << (16 - LastBitLength); 
  1014.     X      } 
  1015.     X
  1016.     X      tree->entry[i].Code = Code; 
  1017.     X      i--; 
  1018.     X   } 
  1019.     X} 
  1020.     X
  1021.     X
  1022.     X/* ----------------------------------------------------------- */ 
  1023.     X
  1024.     Xvoid ReverseBits(tree)
  1025.     Xsf_tree *tree;
  1026.     X /* Reverse the order of all the bits in the above ShannonCode[]
  1027.     X    vector, so that the most significant bit becomes the least
  1028.     X    significant bit. For example, the value 0x1234 (hex) would become
  1029.     X    0x2C48 (hex). */ 
  1030.     X{ 
  1031.     X   int          i;
  1032.     X   word         mask;
  1033.     X   word         revb;
  1034.     X   word         v;
  1035.     X   word         o;
  1036.     X   int          b;
  1037.     X
  1038.     X
  1039.     X   for (i = 0; i <= tree->entries - 1; i++) 
  1040.     X   { 
  1041.     X        /* get original code */ 
  1042.     X      o = tree->entry[i].Code; 
  1043.     X
  1044.     X        /* reverse each bit */ 
  1045.     X      mask = 0x0001;
  1046.     X      revb = 0x8000;
  1047.     X      v = 0;
  1048.     X      for (b = 0; b <= 15; b++) 
  1049.     X      { 
  1050.     X           /* if bit set in mask, then substitute reversed bit */ 
  1051.     X         if ((o & mask) != 0) 
  1052.     X            v = v | revb; 
  1053.     X
  1054.     X           /* advance to next bit */ 
  1055.     X         revb = (revb >> 1);
  1056.     X         mask = (mask << 1);
  1057.     X      } 
  1058.     X
  1059.     X        /* store reversed bits */ 
  1060.     X      tree->entry[i].Code = v; 
  1061.     X   } 
  1062.     X} 
  1063.     X
  1064.     X
  1065.     X/* ----------------------------------------------------------- */ 
  1066.     X
  1067.     Xvoid LoadTree(tree, treesize)
  1068.     Xsf_tree *tree;
  1069.     Xint treesize;
  1070.     X     /* allocate and load a shannon-fano tree from the compressed file */ 
  1071.     X{ 
  1072.     X   tree->entries = treesize; 
  1073.     X   ReadLengths(tree); 
  1074.     X   SortLengths(tree); 
  1075.     X   GenerateTrees(tree); 
  1076.     X   ReverseBits(tree); 
  1077.     X} 
  1078.     X
  1079.     X
  1080.     X/* ----------------------------------------------------------- */ 
  1081.     X
  1082.     Xvoid LoadTrees()
  1083.     X{ 
  1084.     X   /* bit 1... */
  1085.     X   eightK_dictionary = (boolean) ((lrec.general_purpose_bit_flag & 0x02) != 0);
  1086.     X   /* bit 2... */
  1087.     X   lit_tree_present = (boolean) ((lrec.general_purpose_bit_flag & 0x04) != 0);
  1088.     X
  1089.     X   if (eightK_dictionary) 
  1090.     X      dict_bits = 7;
  1091.     X   else 
  1092.     X      dict_bits = 6; 
  1093.     X
  1094.     X   if (lit_tree_present) 
  1095.     X   { 
  1096.     X      minimum_match_length = 3; 
  1097.     X      LoadTree(&lit_tree,256); 
  1098.     X   } 
  1099.     X   else 
  1100.     X      minimum_match_length = 2; 
  1101.     X
  1102.     X   LoadTree(&length_tree,64); 
  1103.     X   LoadTree(&distance_tree,64); 
  1104.     X} 
  1105.     X
  1106.     X
  1107.     X/* ----------------------------------------------------------- */ 
  1108.     X
  1109.     Xvoid ReadTree(tree, dest)
  1110.     Xsf_tree *tree;
  1111.     Xint *dest;
  1112.     X     /* read next byte using a shannon-fano tree */ 
  1113.     X{ 
  1114.     X   int          bits = 0;
  1115.     X   word         cv = 0;
  1116.     X   int          cur = 0;
  1117.     X   int          b;
  1118.     X
  1119.     X   *dest = -1;   /* in case of error */ 
  1120.     X
  1121.     X   for (;;)
  1122.     X   { 
  1123.     X      READBIT(1,b,(int));
  1124.     X      cv = cv | (b << bits);
  1125.     X      bits++; 
  1126.     X
  1127.     X      /* this is a very poor way of decoding shannon-fano.  two quicker
  1128.     X         methods come to mind:
  1129.     X            a) arrange the tree as a huffman-style binary tree with
  1130.     X               a "leaf" indicator at each node,
  1131.     X         and
  1132.     X            b) take advantage of the fact that s-f codes are at most 8
  1133.     X               bits long and alias unused codes for all bits following
  1134.     X               the "leaf" bit.
  1135.     X      */
  1136.     X
  1137.     X      while (tree->entry[cur].BitLength < (byte) bits) 
  1138.     X      { 
  1139.     X         cur++; 
  1140.     X         if (cur >= tree->entries) 
  1141.     X            return; /* data error */
  1142.     X      } 
  1143.     X
  1144.     X      while (tree->entry[cur].BitLength == (byte) bits) 
  1145.     X      { 
  1146.     X         if (tree->entry[cur].Code == cv) 
  1147.     X         { 
  1148.     X            *dest = tree->entry[cur].Value; 
  1149.     X            return; 
  1150.     X         } 
  1151.     X
  1152.     X         cur++; 
  1153.     X         if (cur >= tree->entries) 
  1154.     X            return; /* data error */
  1155.     X      } 
  1156.     X   } 
  1157.     X} 
  1158.     X
  1159.     X
  1160.     X/* ----------------------------------------------------------- */ 
  1161.     X
  1162.     Xvoid unImplode()
  1163.     X     /* expand imploded data */ 
  1164.     X
  1165.     X{ 
  1166.     X   int          lout;
  1167.     X   longint      op;
  1168.     X   int          Length;
  1169.     X   int          Distance;
  1170.     X
  1171.     X   LoadTrees(); 
  1172.     X
  1173.     X   while ((!zipeof) && ((outpos+outcnt) < lrec.uncompressed_size))
  1174.     X   { 
  1175.     X      READBIT(1,lout,(int));
  1176.     X
  1177.     X      if (lout != 0)   /* encoded data is literal data */ 
  1178.     X      { 
  1179.     X         if (lit_tree_present)  /* use Literal Shannon-Fano tree */
  1180.     X            ReadTree(&lit_tree,&lout);
  1181.     X         else 
  1182.     X            READBIT(8,lout,(int));
  1183.     X
  1184.     X         OUTB((byte) lout);
  1185.     X      } 
  1186.     X      else             /* encoded data is sliding dictionary match */
  1187.     X      {                
  1188.     X         READBIT(dict_bits,lout,(int));
  1189.     X         Distance = lout; 
  1190.     X
  1191.     X         ReadTree(&distance_tree,&lout); 
  1192.     X         Distance |= (lout << dict_bits);
  1193.     X         /* using the Distance Shannon-Fano tree, read and decode the
  1194.     X            upper 6 bits of the Distance value */ 
  1195.     X
  1196.     X         ReadTree(&length_tree,&Length); 
  1197.     X         /* using the Length Shannon-Fano tree, read and decode the
  1198.     X            Length value */
  1199.     X
  1200.     X         Length += minimum_match_length; 
  1201.     X         if (Length == (63 + minimum_match_length)) 
  1202.     X         { 
  1203.     X            READBIT(8,lout,(int));
  1204.     X            Length += lout; 
  1205.     X         } 
  1206.     X
  1207.     X        /* move backwards Distance+1 bytes in the output stream, and copy
  1208.     X          Length characters from this position to the output stream.
  1209.     X          (if this position is before the start of the output stream,
  1210.     X          then assume that all the data before the start of the output
  1211.     X          stream is filled with zeros) */ 
  1212.     X
  1213.     X         op = (outpos+outcnt) - Distance - 1L;
  1214.     X
  1215.     X          /* special case- before start of file */
  1216.     X          while ((op < 0L) && (Length > 0)) {
  1217.     X                  OUTB(0);
  1218.     X                  op++;
  1219.     X                  Length--;
  1220.     X          }
  1221.     X
  1222.     X          /* normal copy of data from output buffer */
  1223.     X          {
  1224.     X                  register int ix = (int) (op % OUTBUFSIZ);
  1225.     X
  1226.     X                  /* do a block memory copy if possible */
  1227.     X                  if ( ((ix    +Length) < OUTBUFSIZ) &&
  1228.     X                       ((outcnt+Length) < OUTBUFSIZ) ) {
  1229.     X                          memcpy(outptr,&outbuf[ix],Length);
  1230.     X                          outptr += Length;
  1231.     X                          outcnt += Length;
  1232.     X                  }
  1233.     X
  1234.     X                  /* otherwise copy byte by byte */
  1235.     X                  else while (Length--) {
  1236.     X                          OUTB(outbuf[ix]);
  1237.     X                          if (++ix >= OUTBUFSIZ)
  1238.     X                                  ix = 0;
  1239.     X                  }
  1240.     X         }
  1241.     X      } 
  1242.     X   } 
  1243.     X} 
  1244.     X
  1245.     X/* ---------------------------------------------------------- */
  1246.     X
  1247.     Xvoid extract_member()
  1248.     X{
  1249.     X    unsigned b;
  1250.     X
  1251.     X    bits_left = 0;
  1252.     X    bitbuf = 0;
  1253.     X    incnt = 0;
  1254.     X    outpos = 0L;
  1255.     X    outcnt = 0;
  1256.     X    outptr = outbuf;
  1257.     X    zipeof = 0;
  1258.     X    crc32val = 0xFFFFFFFFL;
  1259.     X
  1260.     X
  1261.     X    /* create the output file with READ and WRITE permissions */
  1262.     X    if (create_output_file())
  1263.     X        exit(1);
  1264.     X
  1265.     X        switch (lrec.compression_method) {
  1266.     X
  1267.     X    case 0:        /* stored */
  1268.     X        {
  1269.     X            if (test_zip)
  1270.     X                printf("Testing: %-12s ", filename);
  1271.     X            if (extract)
  1272.     X                printf(" Extracting: %-12s ", filename);
  1273.     X            while (ReadByte(&b))
  1274.     X                OUTB(b);
  1275.     X        }
  1276.     X        break;
  1277.     X
  1278.     X        case 1: {    /* shrunk */
  1279.     X            if (test_zip)
  1280.     X                printf("Testing: %-12s ", filename);
  1281.     X            if (extract)
  1282.     X                printf("UnShrinking: %-12s ", filename);
  1283.     X            unShrink();
  1284.     X        }
  1285.     X        break;
  1286.     X
  1287.     X    case 2:        /* reduced, factor:1 */
  1288.     X    case 3:        /* reduced, factor:2 */
  1289.     X    case 4:        /* reduced, factor:3 */
  1290.     X        case 5: {    /* reduced, factor:4 */
  1291.     X            if (test_zip)
  1292.     X                printf("Testing: %-12s ", filename);
  1293.     X            if (extract)
  1294.     X                printf("  Expanding: %-12s ", filename);
  1295.     X            unReduce();
  1296.     X        }
  1297.     X        break;
  1298.     X
  1299.     X    case 6: {    /* imploded */
  1300.     X            if (test_zip)
  1301.     X                printf("Testing: %-12s ", filename);
  1302.     X            if (extract)
  1303.     X                printf("  Exploding: %-12s ", filename);
  1304.     X            unImplode();
  1305.     X        }
  1306.     X        break;
  1307.     X
  1308.     X
  1309.     X    default:
  1310.     X        printf("Unknown compression method.");
  1311.     X    }
  1312.     X
  1313.     X
  1314.     X    /* write the last partial buffer, if any */
  1315.     X    if (outcnt > 0) {
  1316.     X        UpdateCRC(outbuf, outcnt);
  1317.     X        Write_file();
  1318.     X    }
  1319.     X
  1320.     X    /* set output file date and time */
  1321.     X    set_file_time();
  1322.     X
  1323.     X    close(outfd);
  1324.     X
  1325.     X    crc32val = -1 - crc32val;
  1326.     X    if (!list_zip) {
  1327.     X      if (crc32val != lrec.crc32) {
  1328.     X        numbad++;
  1329.     X        printf(" Bad");
  1330.     X        if(verbose)
  1331.     X        printf(", CRC %08lx  (should be %08lx)", lrec.crc32, crc32val);
  1332.     X      } else {
  1333.     X        printf(" Ok");
  1334.     X        if (verbose)
  1335.     X        printf(", CRC = %08lx", lrec.crc32);
  1336.     X      }
  1337.     X    printf("\n");
  1338.     X    }
  1339.     X}
  1340.     X
  1341.     X
  1342.     X/* ---------------------------------------------------------- */
  1343.     X
  1344.     Xvoid get_string(len, s)
  1345.     Xint len;
  1346.     Xchar *s;
  1347.     X{
  1348.     X    read(zipfd, s, len);
  1349.     X    s[len] = 0;
  1350.     X}
  1351.     X
  1352.     X/* UNIX support routines: Michael Enkelis */
  1353.     Xget_byte()
  1354.     X{
  1355.     X    byte nibble;
  1356.     X    read(zipfd,&nibble,1);
  1357.     X    return (byte) (nibble & 0xff);
  1358.     X}
  1359.     X
  1360.     Xget_word()
  1361.     X{
  1362.     X    byte nibble[2];
  1363.     X        nibble[0] = get_byte();
  1364.     X        nibble[1] = get_byte();
  1365.     X    return (word) (nibble[0] | nibble[1] << 8);
  1366.     X}
  1367.     X
  1368.     Xget_long()
  1369.     X{
  1370.     X    byte nibble[4];
  1371.     X        nibble[0] = get_byte();
  1372.     X        nibble[1] = get_byte();
  1373.     X        nibble[2] = get_byte();
  1374.     X        nibble[3] = get_byte();
  1375.     X    return (longint)    ((unsigned long) nibble[0] |
  1376.     X            ((unsigned long) nibble[1] << 8)  |
  1377.     X            ((unsigned long) nibble[2] << 16) |
  1378.     X            ((unsigned long) nibble[3] << 24));
  1379.     X}
  1380.     X/** End of added support routines **/
  1381.     X
  1382.     X
  1383.     X/* ---------------------------------------------------------- */
  1384.     X
  1385.     Xvoid process_local_file_header()
  1386.     X{
  1387.     X    byte    Temp;
  1388.     X    byte    yr, mo, dy;    /* parts of a date */
  1389.     X    byte    hh, mm, ss;    /* parts of a time */
  1390.     X
  1391.     X    static char    *mon[] =    /* month abbreviations */
  1392.     X    {
  1393.     X     "Jan", "Feb", "Mar", "Apr",
  1394.     X     "May", "Jun", "Jul", "Aug",
  1395.     X     "Sep", "Oct", "Nov", "Dec"
  1396.     X    };
  1397.     X
  1398.     X    lrec.version_needed_to_extract = get_word();
  1399.     X    lrec.general_purpose_bit_flag = get_word();
  1400.     X    lrec.compression_method = get_word();
  1401.     X    lrec.last_mod_file_time = get_word();
  1402.     X    lrec.last_mod_file_date = get_word();
  1403.     X    lrec.crc32 = get_long();
  1404.     X    lrec.compressed_size = get_long();
  1405.     X    lrec.uncompressed_size = get_long();
  1406.     X    lrec.filename_length = get_word();
  1407.     X    lrec.extra_field_length = get_word();
  1408.     X
  1409.     X    get_string(lrec.filename_length,filename);
  1410.     X    if (unixfy) {
  1411.     X        char *cp;
  1412.     X        for (cp = filename; *cp; ++cp)
  1413.     X            if (isupper(*cp)) *cp = tolower(*cp);
  1414.     X    }
  1415.     X
  1416.     X    get_string(lrec.extra_field_length,extra);
  1417.     X
  1418.     X    yr = (lrec.last_mod_file_date >> 9) & 0x7f;    /* dissect the date */
  1419.     X    mo = (lrec.last_mod_file_date >> 5) & 0x0f;
  1420.     X    dy = lrec.last_mod_file_date & 0x1f;
  1421.     X
  1422.     X    hh = (lrec.last_mod_file_time >> 11) & 0x1f;    /* dissect the time */
  1423.     X    mm = (lrec.last_mod_file_time >> 5) & 0x3f;
  1424.     X    ss = (lrec.last_mod_file_time & 0x1f) * 2;
  1425.     X
  1426.     X    if (debugging) {
  1427.     X    printf("\n\nProcess LOCAL file header.\n");
  1428.     X    Temp = lrec.version_needed_to_extract;
  1429.     X    printf("Version used    : %d.%d\n",Temp/10,Temp%10);
  1430.     X    printf("Bit flags    : ");
  1431.     X    Temp = (lrec.general_purpose_bit_flag & 3);
  1432.     X    if (Temp & 1)
  1433.     X        printf("Encrypted\n");
  1434.     X    if (lrec.compression_method == 6) {
  1435.     X        printf("%dK sliding dictionary, ", (Temp & 2)? 8 : 4);
  1436.     X        printf("%d Shannon-Fano trees", (Temp & 4)? 3 : 2);
  1437.     X    }
  1438.     X    printf("\n");
  1439.     X
  1440.     X    printf("Compression     : %d\n",lrec.compression_method);
  1441.     X    printf("Mod time    :");
  1442.     X        printf("%2d:%02d%cm\n",
  1443.     X               (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
  1444.     X    printf("Mod date    :");
  1445.     X        printf("%2d %3s %02d\n", dy, mon[mo - 1], (yr + 80) % 100);
  1446.     X    printf("Crc32        : %d\n",~lrec.crc32);
  1447.     X    printf("Compressed size    : %d\n",lrec.compressed_size);
  1448.     X    printf("Normal file size: %d\n",lrec.uncompressed_size);
  1449.     X    printf("File name    : %s.%s\n",filename,extra);
  1450.     X    }
  1451.     X
  1452.     X    extract_member();
  1453.     X}
  1454.     X
  1455.     X
  1456.     X/* ---------------------------------------------------------- */
  1457.     X
  1458.     Xvoid process_central_file_header()
  1459.     X{
  1460.     X    central_directory_file_header rec;
  1461.     X    char filename[STRSIZ];
  1462.     X    char extra[STRSIZ];
  1463.     X
  1464.     X    byte    Temp;
  1465.     X    byte    yr, mo, dy;    /* parts of a date */
  1466.     X    byte    hh, mm, ss;    /* parts of a time */
  1467.     X
  1468.     X    static char    *mon[] =    /* month abbreviations */
  1469.     X    {
  1470.     X     "Jan", "Feb", "Mar", "Apr",
  1471.     X     "May", "Jun", "Jul", "Aug",
  1472.     X     "Sep", "Oct", "Nov", "Dec"
  1473.     X    };
  1474.     X
  1475.     X    rec.version_made_by = get_word();
  1476.     X    rec.version_needed_to_extract = get_word();
  1477.     X    rec.general_purpose_bit_flag = get_word();
  1478.     X    rec.compression_method = get_word();
  1479.     X    rec.last_mod_file_time = get_word();
  1480.     X    rec.last_mod_file_date = get_word();
  1481.     X    rec.crc32 = get_long();
  1482.     X    rec.compressed_size = get_long();
  1483.     X    rec.uncompressed_size = get_long();
  1484.     X    rec.filename_length = get_word();
  1485.     X    rec.extra_field_length = get_word();
  1486.     X    rec.file_comment_length = get_word();
  1487.     X    rec.disk_number_start = get_word();
  1488.     X    rec.internal_file_attributes = get_word();
  1489.     X    rec.external_file_attributes = get_long();
  1490.     X    rec.relative_offset_local_header = get_long();
  1491.     X
  1492.     X    get_string(rec.filename_length,filename); 
  1493.     X    if (unixfy) {
  1494.     X        char *cp;
  1495.     X        for (cp = filename; *cp; ++cp)
  1496.     X            if (isupper(*cp)) *cp = tolower(*cp);
  1497.     X    }
  1498.     X
  1499.     X    get_string(rec.extra_field_length,extra); 
  1500.     X    comment = (byte *) (realloc(comment, rec.file_comment_length));
  1501.     X    get_string(rec.file_comment_length,comment); 
  1502.     X
  1503.     X    yr = (rec.last_mod_file_date >> 9) & 0x7f;    /* dissect the date */
  1504.     X    mo = (rec.last_mod_file_date >> 5) & 0x0f;
  1505.     X    dy = rec.last_mod_file_date & 0x1f;
  1506.     X
  1507.     X    hh = (rec.last_mod_file_time >> 11) & 0x1f;    /* dissect the time */
  1508.     X    mm = (rec.last_mod_file_time >> 5) & 0x3f;
  1509.     X    ss = (rec.last_mod_file_time & 0x1f) * 2;
  1510.     X
  1511.     X    if (debugging) {
  1512.     X    printf("\n\nProcess CENTRAL file header.\n");
  1513.     X    printf("Version made by : ");
  1514.     X    Temp = rec.version_made_by;
  1515.     X    switch ((Temp >> 8) & 7) {
  1516.     X        case 0:    printf("MS-DOS");break;
  1517.     X        case 1:    printf("Amiga");break;
  1518.     X        case 2:    printf("VMS");break;
  1519.     X        case 3:    printf("Unix");break;
  1520.     X        case 4:    printf("VM/CMS");break;
  1521.     X        case 5:    printf("Atari");break;
  1522.     X        case 6:    printf("OS/2");break;
  1523.     X        case 7:    printf("Macintosh");break;
  1524.     X        default:
  1525.     X            printf("Unknown");
  1526.     X    }
  1527.     X    printf(" Version %d.%d\n",(Temp & 255)/10,(Temp & 255) % 10);
  1528.     X
  1529.     X    printf("Ver to extract    : %d\n",rec.version_needed_to_extract);
  1530.     X    printf("Bit flags    : ");
  1531.     X    Temp = (rec.general_purpose_bit_flag & 3);
  1532.     X    if (Temp & 1)
  1533.     X        printf("Encrypted\n");
  1534.     X    if (rec.compression_method == 6) {
  1535.     X        printf("%dK sliding dictionary, ", (Temp & 2)? 8 : 4);
  1536.     X        printf("%d Shannon-Fano trees", (Temp & 4)? 3 : 2);
  1537.     X    }
  1538.     X    printf("\n");
  1539.     X
  1540.     X    printf("Compression     : %d\n",rec.compression_method);
  1541.     X    printf("Mod time    :");
  1542.     X        printf("%2d:%02d%cm\n",
  1543.     X               (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
  1544.     X    printf("Mod date    :");
  1545.     X        printf("%2d %3s %02d\n", dy, mon[mo - 1], (yr + 80) % 100);
  1546.     X    printf("Crc32        : %d\n",~rec.crc32);
  1547.     X    printf("Compressed size    : %d\n",rec.compressed_size);
  1548.     X    printf("Normal file size: %d\n",rec.uncompressed_size);
  1549.     X    printf("File name    : %s.%s\n",filename,extra);
  1550.     X    printf("Comment size    : %d\n",rec.file_comment_length);
  1551.     X    printf("Disk start #    : %d\n",rec.disk_number_start);
  1552.     X    printf("File attributes : %d\n",rec.internal_file_attributes);
  1553.     X    printf("Os attributes   : %d\n",rec.external_file_attributes);
  1554.     X    printf("Offset to header: %d\n",rec.relative_offset_local_header);
  1555.     X    printf("Comment         : %s\n",comment); 
  1556.     X    }
  1557.     X
  1558.     X    if (list_zip) {
  1559.     X    Total_files++;
  1560.     X    Total_bytes += rec.uncompressed_size;
  1561.     X    Total_length += rec.compressed_size;
  1562.     X
  1563.     X    printf("%-12s  %8d  ", filename,rec.uncompressed_size);
  1564.     X    if (verbose) {
  1565.     X        printf("%8d  ",rec.compressed_size);
  1566.     X        if (rec.compressed_size)
  1567.     X            printf("%3d%%  ",100L - (100L * rec.compressed_size)/
  1568.     X                rec.uncompressed_size);
  1569.     X        else
  1570.     X            printf("---   ");
  1571.     X    }
  1572.     X
  1573.     X    printf("%2d %3s %02d", dy, mon[mo - 1], (yr + 80) % 100);
  1574.     X
  1575.     X    if (verbose)
  1576.     X        printf("  %2d:%02d%cm",
  1577.     X               (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
  1578.     X    printf("\n");
  1579.     X    }
  1580.     X
  1581.     X}
  1582.     X
  1583.     X
  1584.     X/* ---------------------------------------------------------- */
  1585.     X
  1586.     Xvoid process_end_central_dir()
  1587.     X{
  1588.     X    end_central_dir_record rec;
  1589.     X
  1590.     X    rec.number_this_disk = get_word();
  1591.     X    rec.number_disk_with_start_central_directory = get_word();
  1592.     X    rec.total_entries_central_dir_on_this_disk = get_word();
  1593.     X    rec.total_entries_central_dir = get_word();
  1594.     X    rec.size_central_directory = get_long(); 
  1595.     X    rec.offset_start_central_directory = get_long();
  1596.     X    rec.zipfile_comment_length = get_word();
  1597.     X
  1598.     X    comment = (byte *) (realloc(comment, rec.zipfile_comment_length));
  1599.     X    get_string(rec.zipfile_comment_length,comment); 
  1600.     X
  1601.     X    if (debugging) {
  1602.     X    printf("\n\nProcess END_CENTRAL directory header.\n");
  1603.     X    printf("This disk       : %d\n",rec.number_this_disk);
  1604.     X    printf("Starting disk    : %d\n",
  1605.     X        rec.number_disk_with_start_central_directory);
  1606.     X    printf("Total this disk    : %d\n",
  1607.     X        rec.total_entries_central_dir_on_this_disk);
  1608.     X    printf("Total entries    : %d\n",rec.total_entries_central_dir);
  1609.     X    printf("Central dir size: %d\n",rec.size_central_directory);
  1610.     X    printf("Offset to dir   : %d\n",rec.offset_start_central_directory);
  1611.     X    printf("Comment size    : %d\n",rec.zipfile_comment_length);
  1612.     X    printf("Comment         : %s\n",comment); 
  1613.     X    }
  1614.     X}
  1615.     X
  1616.     X
  1617.     X/* ---------------------------------------------------------- */
  1618.     X
  1619.     Xvoid process_headers()
  1620.     X{ 
  1621.     X    int i;
  1622.     X    char sig[4];
  1623.     X
  1624.     X    if (list_zip) {
  1625.     X     if (verbose) {
  1626.     X     printf("\nName          Length    Size now   SF   Date       Time");
  1627.     X     printf("\n============  ========  ========  ====  =========  ========\n");
  1628.     X     } else {
  1629.     X     printf("\nName          Length    Date");
  1630.     X     printf("\n============  ========  =========\n");
  1631.     X     }
  1632.     X    }
  1633.     X
  1634.     X    while (1)
  1635.     X    { 
  1636.     X    for (i=0; i<4; i++)        /* Read the ZIP file sig */
  1637.     X        sig[i] = get_byte();
  1638.     X
  1639.     X    if (strncmp(sig,local_file_header_signature,4) == 0)
  1640.     X        process_local_file_header();
  1641.     X    else
  1642.     X    if (strncmp(sig,central_file_header_signature,4) == 0)
  1643.     X        process_central_file_header();
  1644.     X    else
  1645.     X    if (strncmp(sig,end_central_dir_signature,4) == 0)
  1646.     X        {
  1647.     X            process_end_central_dir(); 
  1648.     X            if (test_zip) {
  1649.     X             if (numbad < 1)
  1650.     X                printf("No errors detected\n");
  1651.     X             else
  1652.     X             if (numbad == 1)
  1653.     X                printf("One error detected\n");
  1654.     X             else
  1655.     X                printf("%d errors detected\n",numbad);
  1656.     X            }
  1657.     X            if (list_zip) {
  1658.     X             if (verbose) {
  1659.     X              printf("        ====  ========  ========  ====  \n");
  1660.     X             printf("Total:  %4d  %8d  %8d  ",
  1661.     X                Total_files,Total_bytes,Total_length);
  1662.     X             if (Total_length)
  1663.     X                printf("%3d%%\n", 100 - (100 * Total_length)/
  1664.     X                    Total_bytes);
  1665.     X            else
  1666.     X                printf("---\n");
  1667.     X             } else {
  1668.     X             printf("        ====  ========\n");
  1669.     X             printf("Total:  %4d  %8d\n",
  1670.     X                Total_files,Total_bytes);
  1671.     X             }
  1672.     X            }
  1673.     X            if (strlen(comment) && dsp_comment)
  1674.     X                printf("%s\n",comment); 
  1675.     X            return;
  1676.     X        } 
  1677.     X    else 
  1678.     X        { 
  1679.     X            printf("Invalid Zipfile Header\n"); 
  1680.     X            return;
  1681.     X        } 
  1682.     X    } 
  1683.     X}
  1684.     X
  1685.     X
  1686.     X
  1687.     X/* ---------------------------------------------------------- */
  1688.     X
  1689.     Xvoid extract_zipfile()
  1690.     X{
  1691.     X    /*
  1692.     X     * open the zipfile for reading and in BINARY mode to prevent cr/lf
  1693.     X     * translation, which would corrupt the bitstreams 
  1694.     X     */
  1695.     X
  1696.     X    if (open_input_file())
  1697.     X        exit(1);
  1698.     X
  1699.     X    process_headers();
  1700.     X
  1701.     X    close(zipfd);
  1702.     X}
  1703.     X
  1704.     X
  1705.     X/* ---------------------------------------------------------- */
  1706.     X/*
  1707.     X * main program
  1708.     X *
  1709.     X */
  1710.     X
  1711.     Xvoid main(argc, argv)
  1712.     Xint argc;
  1713.     Xchar **argv;
  1714.     X{
  1715.     X
  1716.     X#ifdef USE_GETOPT
  1717.     X    int c;                /* next option letter */
  1718.     X    int count = 0;            /* count of required options seen */
  1719.     X
  1720.     X    extern int optind;        /* from getopt: next arg to process */
  1721.     X    extern int opterr;        /* used by getopt */
  1722.     X    extern char *optarg;
  1723.     X
  1724.     X    opterr = 0;            /* so getopt won't print err msg */
  1725.     X
  1726.     X    while ((c = getopt (argc, argv, "cdltuv")) != EOF)
  1727.     X    {
  1728.     X    switch (c) {
  1729.     X        case 'c':    dsp_comment =0; break;
  1730.     X        case 'd':    debugging++;dsp_comment =0; break;
  1731.     X        case 'l':    list_zip =1;extract =0; break;
  1732.     X        case 't':    test_zip =1;extract =0; break;
  1733.     X        case 'u':    unixfy =0; break;
  1734.     X        case 'v':    verbose++; break;
  1735.     X        default:    short_help();
  1736.     X        }
  1737.     X    }
  1738.     X
  1739.     X    if (argv[optind] != NULL)
  1740.     X        strcpy(zipfn,argv[optind]);
  1741.     X    else
  1742.     X        long_help();
  1743.     X
  1744.     X    /* .ZIP default if none provided by user */
  1745.     X    if (strchr(zipfn,'.') == NULL)
  1746.     X    strcat(zipfn,".zip");
  1747.     X#else
  1748.     X    if (argc != 2)
  1749.     X        long_help();
  1750.     X
  1751.     X    /* .ZIP default if none provided by user */
  1752.     X    strcpy(zipfn, argv[1]);
  1753.     X    if (strchr(zipfn, '.') == NULL)
  1754.     X        strcat(zipfn, ".zip");
  1755.     X#endif
  1756.     X
  1757.     X        /* allocate i/o buffers */
  1758.     X    inbuf = (byte *) (malloc(INBUFSIZ));
  1759.     X    outbuf = (byte *) (malloc(OUTBUFSIZ));
  1760.     X    comment = (byte *) (malloc(STRSIZ));
  1761.     X    if ((inbuf == NULL) || (outbuf == NULL) || (comment == NULL)) {
  1762.     X        printf("Can't allocate buffers!\n");
  1763.     X        exit(1);
  1764.     X    }
  1765.     X
  1766.     X        /* do the job... */
  1767.     X        extract_zipfile();
  1768.     X    exit(0);
  1769.     X}
  1770.     X
  1771.     Xlong_help()
  1772.     X{
  1773.     Xprintf("\nUnZip:  Zipfile Extract Version:%s Patchlevel:%d",VERSION,PATCH);
  1774.     Xprintf(";  (C) 1989 Samuel H. Smith\n");
  1775.     Xprintf("Courtesy of:  S.H.Smith and The Tool Shop BBS, (602) 279-2673.");
  1776.     Xprintf("\n\n");
  1777.     Xprintf("UNIX mods by: Michael Enkelis\n\n");
  1778.     Xprintf("You may copy and distribute this program freely, provided that:\n");
  1779.     Xprintf("    1)   No fee is charged for such copying and distribution, and\n");
  1780.     Xprintf("    2)   It is distributed ONLY in its original, unmodified state.");
  1781.     Xprintf("\n\n");
  1782.     Xprintf("If you wish to distribute a modified version of this program, you MUST\n");
  1783.     Xprintf("include the source code.\n\n");
  1784.     Xprintf("If you modify this program, I would appreciate a copy of the  new source\n");
  1785.     Xprintf("code.   I am holding the copyright on the source code, so please don't\n");
  1786.     Xprintf("delete my name from the program files or from the documentation.\n\n");
  1787.     Xprintf("IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n");
  1788.     Xprintf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n");
  1789.     Xprintf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n");
  1790.     Xprintf("CLAIM BY ANY OTHER PARTY.\n\n");
  1791.     Xshort_help();
  1792.     Xexit(1);
  1793.     X}
  1794.     X
  1795.     Xshort_help()
  1796.     X{
  1797.     X    printf("Usage:    UnZip -chltuv FILE[.zip]\n\n");
  1798.     X    printf("  -c    Don't display coments.\n");
  1799.     X    printf("  -h    This help listing.\n");
  1800.     X    printf("  -l    List zip archive.\n");
  1801.     X    printf("  -t    Test zip archive.\n");
  1802.     X    printf("  -u    Don't convert filenames to lowercase.\n");
  1803.     X    printf("  -v    Verbose output.\n\n");
  1804.     X    exit(1);
  1805.     X}
  1806. SHAR_EOF
  1807. if test 42309 -ne "`wc -c < 'unzipbsd.c'`"
  1808. then
  1809.     echo shar: error transmitting "'unzipbsd.c'" '(should have been 42309 characters)'
  1810. fi
  1811. fi # end of overwriting check
  1812. echo shar: extracting "'crc32.c'" '(7120 characters)'
  1813. if test -f 'crc32.c'
  1814. then
  1815.     echo shar: will not over-write existing file "'crc32.c'"
  1816. else
  1817. sed 's/^    X//' << \SHAR_EOF > 'crc32.c'
  1818.     X
  1819.     X  /* ============================================================= */
  1820.     X  /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or       */
  1821.     X  /*  code or tables extracted from it, as desired without restriction.     */
  1822.     X  /*                                                                        */
  1823.     X  /*  First, the polynomial itself and its table of feedback terms.  The    */
  1824.     X  /*  polynomial is                                                         */
  1825.     X  /*  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0   */
  1826.     X  /*                                                                        */
  1827.     X  /*  Note that we take it "backwards" and put the highest-order term in    */
  1828.     X  /*  the lowest-order bit.  The X^32 term is "implied"; the LSB is the     */
  1829.     X  /*  X^31 term, etc.  The X^0 term (usually shown as "+1") results in      */
  1830.     X  /*  the MSB being 1.                                                      */
  1831.     X  /*                                                                        */
  1832.     X  /*  Note that the usual hardware shift register implementation, which     */
  1833.     X  /*  is what we're using (we're merely optimizing it by doing eight-bit    */
  1834.     X  /*  chunks at a time) shifts bits into the lowest-order term.  In our     */
  1835.     X  /*  implementation, that means shifting towards the right.  Why do we     */
  1836.     X  /*  do it this way?  Because the calculated CRC must be transmitted in    */
  1837.     X  /*  order from highest-order term to lowest-order term.  UARTs transmit   */
  1838.     X  /*  characters in order from LSB to MSB.  By storing the CRC this way,    */
  1839.     X  /*  we hand it to the UART in the order low-byte to high-byte; the UART   */
  1840.     X  /*  sends each low-bit to hight-bit; and the result is transmission bit   */
  1841.     X  /*  by bit from highest- to lowest-order term without requiring any bit   */
  1842.     X  /*  shuffling on our part.  Reception works similarly.                    */
  1843.     X  /*                                                                        */
  1844.     X  /*  The feedback terms table consists of 256, 32-bit entries.  Notes:     */
  1845.     X  /*                                                                        */
  1846.     X  /*      The table can be generated at runtime if desired; code to do so   */
  1847.     X  /*      is shown later.  It might not be obvious, but the feedback        */
  1848.     X  /*      terms simply represent the results of eight shift/xor opera-      */
  1849.     X  /*      tions for all combinations of data and CRC register values.       */
  1850.     X  /*                                                                        */
  1851.     X  /*      The values must be right-shifted by eight bits by the "updcrc"    */
  1852.     X  /*      logic; the shift must be unsigned (bring in zeroes).  On some     */
  1853.     X  /*      hardware you could probably optimize the shift in assembler by    */
  1854.     X  /*      using byte-swap instructions.                                     */
  1855.     X  /*      polynomial $edb88320                                              */
  1856.     X  /*                                                                        */
  1857.     X  /*  --------------------------------------------------------------------  */
  1858.     X
  1859.     Xlong crc_32_tab[] = {
  1860.     X      0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  1861.     X      0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  1862.     X      0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  1863.     X      0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  1864.     X      0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  1865.     X      0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  1866.     X      0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  1867.     X      0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  1868.     X      0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  1869.     X      0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  1870.     X      0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  1871.     X      0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  1872.     X      0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  1873.     X      0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  1874.     X      0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  1875.     X      0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  1876.     X      0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  1877.     X      0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  1878.     X      0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  1879.     X      0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  1880.     X      0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  1881.     X      0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  1882.     X      0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  1883.     X      0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  1884.     X      0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  1885.     X      0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  1886.     X      0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  1887.     X      0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  1888.     X      0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  1889.     X      0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  1890.     X      0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  1891.     X      0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  1892.     X      0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  1893.     X      0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  1894.     X      0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  1895.     X      0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  1896.     X      0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  1897.     X      0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  1898.     X      0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  1899.     X      0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  1900.     X      0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  1901.     X      0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  1902.     X      0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  1903.     X      0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  1904.     X      0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  1905.     X      0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  1906.     X      0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  1907.     X      0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  1908.     X      0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  1909.     X      0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  1910.     X      0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  1911.     X      0x2d02ef8dL
  1912.     X   };
  1913.     X
  1914.     X/* ------------------------------------------------------------- */
  1915.     X
  1916.     Xextern long crc32val;
  1917.     X
  1918.     Xvoid UpdateCRC(s, len)
  1919.     Xregister char *s;
  1920.     Xregister int len;
  1921.     X /* update running CRC calculation with contents of a buffer */
  1922.     X{
  1923.     X   int i;
  1924.     X   for (i = 0;  i < len;  i ++) {
  1925.     X      crc32val = crc_32_tab[(int) ((crc32val) ^ (s[i])) & 0xff] ^
  1926.     X         (((crc32val) >> 8) & 0x00FFFFFFL);
  1927.     X   }
  1928.     X}
  1929. SHAR_EOF
  1930. if test 7120 -ne "`wc -c < 'crc32.c'`"
  1931. then
  1932.     echo shar: error transmitting "'crc32.c'" '(should have been 7120 characters)'
  1933. fi
  1934. fi # end of overwriting check
  1935. echo shar: extracting "'patchlevel.h'" '(16 characters)'
  1936. if test -f 'patchlevel.h'
  1937. then
  1938.     echo shar: will not over-write existing file "'patchlevel.h'"
  1939. else
  1940. sed 's/^    X//' << \SHAR_EOF > 'patchlevel.h'
  1941.     X#define PATCH 0
  1942. SHAR_EOF
  1943. if test 16 -ne "`wc -c < 'patchlevel.h'`"
  1944. then
  1945.     echo shar: error transmitting "'patchlevel.h'" '(should have been 16 characters)'
  1946. fi
  1947. fi # end of overwriting check
  1948. echo shar: extracting "'unzip.doc'" '(3086 characters)'
  1949. if test -f 'unzip.doc'
  1950. then
  1951.     echo shar: will not over-write existing file "'unzip.doc'"
  1952. else
  1953. sed 's/^    X//' << \SHAR_EOF > 'unzip.doc'
  1954.     X  
  1955.     X                                   UnZip
  1956.     X  
  1957.     X                           Version 2.0.1, 09-16-89
  1958.     X  
  1959.     X                           Zipfile Extract Utility
  1960.     X  
  1961.     X          Copyright (C) 1989 Samuel H. Smith;  ALL RIGHTS RESERVED
  1962.     X  
  1963.     X  
  1964.     X'UnZip' is a small Zipfile extract utility.   It is written to be as
  1965.     Xsmall and portable as possible -- ideal as a starting point for handling
  1966.     X.ZIP files in non-IBM environments.
  1967.     X
  1968.     XSource code is provided in C and Turbo Pascal.  If you port this program
  1969.     Xto a non-IBM system, I would appreciate a copy of the ported source and
  1970.     Xexec files.
  1971.     X
  1972.     X
  1973.     XUsage
  1974.     X-----
  1975.     X   unz filename[.zip]           ;pascal language version
  1976.     X   unzip filename[.zip]         ;C language version
  1977.     X
  1978.     X
  1979.     XRevision history
  1980.     X----------------
  1981.     X
  1982.     X3-3-89
  1983.     X   Initial alpha test release.
  1984.     X
  1985.     X3-5-89
  1986.     X   First fully operational release.  Does not implement CRC verification,
  1987.     X   but should correctly unzip all compression methods.
  1988.     X
  1989.     X3-6-89
  1990.     X   Corrected end-of-file detection in both shrink and reduce expanders.
  1991.     X   Resulting files should now always have the correct size.  Added ".ZIP"
  1992.     X   default to unzip.c to match calling conventions of unz.pas.
  1993.     X
  1994.     X3-8-89
  1995.     X   Moved machine and operating-system specific code to a block starting
  1996.     X   around line 180.  Added code to swap bytes on host machines that
  1997.     X   store the high order bytes in lower address locations than the low
  1998.     X   order bytes.
  1999.     X
  2000.     X3-15-89
  2001.     X   Added CRC checking in UNZIP.C.  Speeded operation by about 150%.
  2002.     X
  2003.     X   I'm spending my time on the C version now and don't plan to do any
  2004.     X   further work on the pascal.  If you're using the pascal version
  2005.     X   please contact me.
  2006.     X
  2007.     X9-9-89
  2008.     X   Addition of new "un-implode" logic to handle new compression format
  2009.     X   included with PKZ101.
  2010.     X
  2011.     X
  2012.     X
  2013.     XLICENSE
  2014.     X=======
  2015.     X
  2016.     XYou may copy and distribute this program freely, provided that:
  2017.     X    1)   No fee is charged for such copying and distribution, and
  2018.     X    2)   It is distributed ONLY in its original, unmodified state.
  2019.     X
  2020.     XIf you wish to distribute a modified version of this program, you MUST
  2021.     Xinclude the source code.
  2022.     X
  2023.     XIf you modify this program, I would appreciate a copy of the new source
  2024.     Xcode.  I am holding the copyright on the source code, so please don't
  2025.     Xdelete my name from the program files or from the documentation.
  2026.     X
  2027.     X
  2028.     XSUPPORT
  2029.     X=======
  2030.     X
  2031.     XI work very hard to produce a software package of the highest quality
  2032.     Xand functionality.  I try to look into all reported bugs, and will
  2033.     Xgenerally fix reported problems within a few days.
  2034.     X
  2035.     XIN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST
  2036.     XPROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES
  2037.     XARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY
  2038.     XCLAIM BY ANY OTHER PARTY.
  2039.     X
  2040.     XIf you have any questions, bugs, or suggestions, please contact me at:
  2041.     X
  2042.     X                  The Tool Shop BBS
  2043.     X                  (602) 279-2673 (FREE LINE, USR 2400)
  2044.     X                  (602) 264-3969 (HST 9600)
  2045.     X                  (602) 270-0239 (HAYES 9600)
  2046.     X
  2047.     XThe latest version is always available for downloading.  (Except
  2048.     Xpossibly this portable version.)
  2049.     X
  2050.     XEnjoy!     Samuel H. Smith
  2051.     X           Author and Sysop of The Tool Shop.
  2052.     X   
  2053. SHAR_EOF
  2054. if test 3086 -ne "`wc -c < 'unzip.doc'`"
  2055. then
  2056.     echo shar: error transmitting "'unzip.doc'" '(should have been 3086 characters)'
  2057. fi
  2058. fi # end of overwriting check
  2059. #    End of shell archive
  2060. exit 0
  2061. -- 
  2062.  _ _ _                          __
  2063. ' ) ) )      /          /)     /  `       /      /)    Michael Enkelis
  2064.  / / / o _. /_  __. _  //     /--   __   /_  _  // o _     tektronix!vice!michaele
  2065. / ' (_(_(__/ /_(_(_(<_(/_    (___, /) )_/ <_(<_(/_(_/_)_    (503) 627-4099
  2066.  
  2067.